﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;

using System.Xml.Serialization;
using System.ComponentModel;
using System.Diagnostics;

#if (LINQ)
using System.Data.Linq;
using System.Linq;
#endif

using System.Runtime.Serialization;

using Robin.LightNing.Interfaces;
using Robin.LightNing.DynamicQuery;
using System.Reflection;

namespace Robin.LightNing.Core
{
    /// <summary>
    /// 
    /// </summary>
    /// <returns></returns>
    public delegate object ModifiedByEventHandler();

    /// <summary>
    /// 实体基类.
    /// </summary>
    /// <remarks>
    /// 在RobinLightNing中,例如Employees (继承自 <see cref="rbEntity"/>)或EmployeesCollection (继承自 <see cref="rbEntityCollection"/>) 映射到数据库中的一个表或视图.
    /// 基于视图的对象是只读的，虽然在某些情况下，可以做出更新操作.
    /// 表必须要有主键.可以使用存储过程或动态sql的方式进行GRUD操作(create, retrieve, update, delete). 
    /// </remarks>
    /// <example>
    /// 一个实体可以单独存在.
    /// <code>
    /// Employees entity = new Employees();
    /// if(entity.LoadByPrimaryKey(10))
    /// {
    ///     entity.Salary = entity.Salary.Value * 1.05m;
    ///     entity.Save();
    /// }
    /// </code>
    /// 或者可以作为集合的一部分
    /// <code>
    /// EmployeesCollection collection = new EmployeesCollection();
    /// entity.LastName = "Jones";
    /// entity.FirstName = "Alice";
    /// collection.Save();
    /// </code>
    /// rbEntity的查询机制可以用于加载数据,但是查询必须只返回一行. 如果Query.Load()只检索到一行，返回true,否则返回false.
    /// 如果返回超过一行，则抛出异常.生成的实体，也包含LoadByPrimaryKey方法.
    /// <code>
    /// Employees entity = new Employees();
    /// entity.Query.rb.Top = 1;
    /// entity.Query.OrderBy(entity.Query.Salary.Descending);
    /// if(entity.Query.Load())
    /// {
    ///		// record was loaded, I wish I made his salary !
    /// }
    /// </code>
    /// </example>
    [Serializable]
    [XmlType(IncludeInSchema = false)]
#if (!WindowsCE)
    [DataContract]
#endif
    public abstract class rbEntity : IVisitable, IEditableObject, IEntity, ICommittable, INotifyPropertyChanged, IDataErrorInfo
#if (WebBinding)
       , ICustomTypeDescriptor
#endif
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        public rbEntity()
        {
            rowState = rbDataRowState.Added;
            currentValues.FirstAccess += new rbSmartDictionary.rbSmartDictionaryFirstAccessEventHandler(CurrentValues_OnFirstAccess);
        }

        /// <summary>
        /// 当列为字符型的时候，并且长度为0的时候，是否要转换。如果为true，那么一个0长度的字符串在数据库中设置为NULL
        /// </summary>
        static public bool ConvertEmptyStringToNull = false;

        private void CurrentValues_OnFirstAccess(rbSmartDictionary smartDictionary)
        {
            smartDictionary.Allocate(rb.Meta.Columns.Count);

            foreach (rbColumnMetadata col in rb.Meta.Columns)
            {
                currentValues.SetOrdinal(col.Name, col.Ordinal);
            }
        }

        /// <summary>
        /// 动态查询成功执行在单个实体上的时候调用.如果返回多行，返回false.
        /// </summary>
        /// <remarks>
        /// 如果要重载，需要向下调用此方法用于填充实体
        /// </remarks>
        /// <param name="query">刚加载完的查询</param>
        /// <param name="table">保存即将变化的实体数据的DataTable</param>
        /// <returns>如果记录存在，返回True</returns>
        protected bool OnQueryLoaded(rbDynamicQuery query, DataTable table)
        {
            if (table.Rows.Count > 1)
            {
                throw new Exception("一个实体只能保存一条数据");
            }

            bool dataFound = this.PopulateEntity(table);

            if (query.rb2.PrefetchMaps != null)
            {
                bool firstTime = true;

                // Add ourself into the list with a map name of string.Empty
                Dictionary<string, Dictionary<object, rbEntityCollectionBase>> collections = new Dictionary<string, Dictionary<object, rbEntityCollectionBase>>();
                Dictionary<object, rbEntityCollectionBase> me = new Dictionary<object, rbEntityCollectionBase>();
                collections[string.Empty] = me;

                this.rb.IsLazyLoadDisabled = true;

                foreach (rbPrefetchMap map in query.rb2.PrefetchMaps)
                {
                    DataTable preFetchedTable = map.Table;

                    Dictionary<object, rbEntityCollectionBase> loadedCollections = null;
                    Dictionary<object, rbEntityCollectionBase> newCollection = new Dictionary<object, rbEntityCollectionBase>();

                    if (map.Path == string.Empty)
                    {
                        loadedCollections = collections[string.Empty];

                        if (firstTime)
                        {
                            ProcessEntityForPrefetch(this, map, newCollection);
                            firstTime = true;
                        }
                    }
                    else
                    {
                        loadedCollections = collections[map.Path];
                    }

                    foreach (rbEntityCollectionBase collection in loadedCollections.Values)
                    {
                        foreach (rbEntity obj in collection)
                        {
                            ProcessEntityForPrefetch(obj, map, newCollection);
                        }
                    }

                    Dictionary<string, int> ordinals = null;
                    DataRowCollection rows = preFetchedTable.Rows;
                    int count = rows.Count;
                    for (int i = 0; i < count; i++)
                    {
                        DataRow row = rows[i];

                        object key = null;

                        // Avoid doing the Split() if we can
                        if (map.IsMultiPartKey)
                        {
                            key = string.Empty;

                            string[] columns = map.MyColumnName.Split(',');
                            foreach (string col in columns)
                            {
                                key += Convert.ToString(row[col]);
                            }
                        }
                        else
                        {
                            key = row[map.MyColumnName];
                        }

                        rbEntityCollectionBase c = newCollection[key];

                        IEntityCollection iColl = c as IEntityCollection;
                        ordinals = iColl.PopulateCollection(row, ordinals);
                    }

                    collections[map.PropertyName] = newCollection;
                }
            }

            return dataFound;
        }

        /// <summary>
        /// 内部使用.避免重复代码.
        /// </summary>
        static private void ProcessEntityForPrefetch(rbEntity obj, rbPrefetchMap map, Dictionary<object, rbEntityCollectionBase> newCollection)
        {
            obj.rb.IsLazyLoadDisabled = true;

            object key = null;

            // Avoid doing the Split() if we can
            if (map.IsMultiPartKey)
            {
                key = string.Empty;

                string[] columns = map.ParentColumnName.Split(',');
                foreach (string col in columns)
                {
                    key += Convert.ToString(obj.GetColumn(col));
                }
            }
            else
            {
                key = obj.GetColumn(map.ParentColumnName);
            }

            IEntity iEntity = obj as IEntity;
            newCollection[key] = iEntity.CreateCollection(map.PropertyName);
        }


        /// <summary>
        /// 为SQL(包含 {0} {1} {2} 这样的语法)创建参数
        /// </summary>
        /// <param name="parameters">即将变为参数的object对象数组</param>
        /// <returns>参数集合</returns>
        static private rbParameters PackageParameters(params object[] parameters)
        {
            rbParameters rbParams = null;

            int i = 0;
            string sIndex = String.Empty;
            string param = String.Empty;

            if (parameters != null)
            {
                rbParams = new rbParameters();

                foreach (object o in parameters)
                {
                    sIndex = i.ToString();
                    param = "p" + sIndex;
                    rbParams.Add(param, o);
                    i++;
                }
            }

            return rbParams;
        }

        /// <summary>
        /// rbEntity类调用数据访问器的时候内部调用.该方法封装了常用的逻辑. 
        /// </summary>
        /// <returns>rbDataRequest</returns>
        /// <seealso cref="rbDataRequest"/><seealso cref="rbDataProvider"/><seealso cref="IDataProvider"/>
        protected rbDataRequest CreateRequest()
        {
            rbDataRequest request = new rbDataRequest();
            request.Caller = this;

            rbConnection conn = this.rb.Connection;

            request.ConnectionString = conn.ConnectionString;
            request.CommandTimeout = conn.CommandTimeout;
            request.DataID = this.Meta.DataID;
            request.ProviderMetadata = this.Meta.GetProviderMetadata(conn.ProviderMetadataKey);
            request.SelectedColumns = selectedColumns;

            request.Catalog = conn.Catalog;
            request.Schema = conn.Schema;

            return request;
        }

        /// <summary>
        /// 返回实体基于配置文件中的providerMetadataKey的rbProviderSpecificMetadata.
        /// </summary>
        /// <returns></returns>
        private rbProviderSpecificMetadata GetProviderMetadata()
        {
            // We're on our own, use our own rbProviderSpecificMetadata
            string key = this.rb.Connection.ProviderMetadataKey;
            return this.Meta.GetProviderMetadata(key);
        }

        /// <summary>
        /// 复制一个实体,仅复制值.没有层级属性或集合可以被复制.
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <returns>新复制的对象</returns>
        virtual public T Clone<T>() where T : rbEntity, new()
        {
            T entity = new T();

            entity.currentValues = new rbSmartDictionary(currentValues);
            entity.rowState = rowState;

            if (originalValues != null)
            {
                entity.originalValues = new rbSmartDictionary(originalValues);
            }

            if (m_modifiedColumns != null)
            {
                entity.m_modifiedColumns = new List<string>(m_modifiedColumns);
            }

            return entity;
        }

        #region Debugger Display

        /// <summary>
        /// 快速查看实体的值很好的方法.当你在调试器中检查实体的时候才会存在.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden | DebuggerBrowsableState.Never)]
#endif
        virtual protected rbEntityDebuggerView[] Debug
        {
            get
            {
                rbEntityDebuggerView[] data = new rbEntityDebuggerView[currentValues.Count + 1];

                data[0].Property = "(RowState)";
                data[0].Data = rowState;

                string columnName = "";

                for(int index = 0; index < currentValues.Count; index++)
                {
                    columnName = currentValues.IndexToColumnName(index);

                    int i = index + 1;

                    data[i].Property = columnName;
                    data[i].Data = currentValues[columnName] == DBNull.Value ? null : currentValues[columnName];
                }

                return data;
            }
        }

        #endregion

        #region Virtual Methods

        /// <summary>
        /// 实体的只读元数据
        /// </summary>
        /// <remarks>
        /// 下面的例子展示了通过<see cref="IMetadata"/>接口遍历<see cref="rbColumnMetadataCollection"/>集合. 有很多有用的信息.
        /// <code>
        /// public partial class Employees : rbEmployees
        /// {
        /// 	public void CustomMethod()
        /// 	{
        /// 		foreach(rbColumnMetadata col in this.Meta.Columns)
        /// 		{
        /// 			if(col.IsInPrimaryKey)
        /// 			{
        /// 				// 执行逻辑 ...
        /// 			}
        /// 		}
        /// 	}
        /// }
        /// </code>
        /// </remarks>
        /// <seealso cref="rbColumnMetadata"/>
        /// <seealso cref="rbColumnMetadataCollection"/>
        /// <seealso cref="rbProviderSpecificMetadata"/>
        virtual protected IMetadata Meta
        {
            get { return null; }
        }

        /// <summary>
        ///创建实例，很少用
        /// </summary>
        /// <returns></returns>
        virtual public rbEntity CreateInstance()
        {
            return null;
        }

        /// <summary>
        /// 执行绑定的时候内部使用.
        /// </summary>
        /// <returns>扩展属性列表</returns>
        virtual protected internal List<rbPropertyDescriptor> GetLocalBindingProperties()
        {
            return null;
        }

        /// <summary>
        /// 执行绑定的时候内部使用.
        /// </summary>
        /// <returns>层次属性或集合列表</returns>
        virtual protected internal List<rbPropertyDescriptor> GetHierarchicalProperties()
        {
            return new List<rbPropertyDescriptor>();
        }

        /// <summary>
        /// 实体需要连接的时候调用.可以用于重写默认连接. 
        /// </summary>
        /// <returns></returns>
        virtual protected string GetConnectionName()
        {
            return null;
        }

        /// <summary>
        /// 生成的类中重写.
        /// </summary>
        /// <param name="values"></param>
        virtual public void SetProperties(IDictionary values)
        {

        }

        /// <summary>
        /// 生成的类中重写.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="value"></param>
        virtual public void SetProperty(string name, object value)
        {

        }

        /// <summary>
        /// 生成的类中重写用于支持动态查询的预获取逻辑
        /// </summary>
        /// <param name="collectionName">集合的字符串名称, 例如, "OrdersCollectionByEmployeeID"</param>
        /// <returns>正确的集合类型, 例如, "OrdersCollection"</returns>
        virtual protected rbEntityCollectionBase CreateCollectionForPrefetch(string collectionName)
        {
            return null;
        }

        /// <summary>
        /// 当实体已经包含一个RowState为Added的时候，对第一个属性进行读取或设置的时候调用.
        /// 该方法可以对新创建的实例进行任何属性的初始化.
        /// </summary>
        virtual internal protected void ApplyDefaults()
        {

        }

        #endregion

        internal PropertyDescriptorCollection GetAllHierarchicalProperties(PropertyDescriptorCollection props)
        {
            ArrayList tempColl = new ArrayList();

            Type type = this.GetType();
            PropertyDescriptor prop = null;
            
            for (int i = 0; i < props.Count; i++)
            {
                prop = props[i];

                Type propType = prop.PropertyType;

                if (propType.IsClass && !propType.IsAbstract)
                {
                    if (propType.IsSubclassOf(typeof(rbEntityCollectionBase)))
                    {
                        tempColl.Add(prop);
                    }
                    else if (propType.IsSubclassOf(typeof(rbEntity)))
                    {
                        tempColl.Add(prop);
                    }
                }
            }

            PropertyDescriptorCollection theProps =
                new PropertyDescriptorCollection((PropertyDescriptor[])tempColl.ToArray(typeof(PropertyDescriptor)));

            return theProps;
        }

        /// <summary>
        /// 代理调用，以确定扩展的列是否需要序列化.
        /// </summary>
        /// <remarks>
        /// 扩展列不代表数据库表中的列,它们可以通过JOIN带回或直接为实体添加扩展属性.
        /// </remarks>
        /// <returns></returns>
        public Dictionary<string, object> GetExtraColumns()
        {
            Dictionary<string, object> extraColumns = new Dictionary<string, object>();

            if (this.currentValues != null)
            {
                rbColumnMetadataCollection cols = this.rb.Meta.Columns;

                foreach (string column in this.currentValues.Keys)
                {
                    if (cols.FindByColumnName(column) == null)
                    {
                        // Turn DBNull.Value into "null"
                        object o = this.currentValues[column];
                        extraColumns[column] = (o == DBNull.Value) ? null : o;
                    }
                }
            }

            return extraColumns;
        }

        /// <summary>
        /// 使用rbDataContractSerializer序列化从GetExtraColumns()返回的字典.
        /// </summary>
        /// <returns>序列化的字典，如果无扩展列的时候返回null</returns>
        protected string GetExtraColumnsSerialized()
        {
            Dictionary<string, object> ext = this.GetExtraColumns();

            if (ext.Values.Count > 0)
            {
#if (!WindowsCE)
                return rbDataContractSerializer.ToXml(ext);
#else
                return null;
#endif
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 代理（proxies）调用
        /// </summary>
        /// <param name="extraColumns"></param>
        public void SetExtraColumns(Dictionary<string, object> extraColumns)
        {
            if (extraColumns != null)
            {
                foreach (string column in extraColumns.Keys)
                {
                    SetColumn(column, extraColumns[column], true);
                }
            }
        }

        #region INotifyPropertyChanged Members

        /// <summary>
        /// PropertyChanged事件处理器
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                propertyChanged += value;
            }
            remove
            {
                propertyChanged -= value;
            }
        }

        [NonSerialized]
#if (!WindowsCE)
        [IgnoreDataMember]
#endif
        private PropertyChangedEventHandler propertyChanged;

        /// <summary>
        /// 属性改变的时候,INotifyPropertyChanged支持该方法被调用.
        /// </summary>
        /// <param name="propertyName"></param>
        virtual public void OnPropertyChanged(string propertyName)
        {
            if (propertyChanged != null)
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion

        #region 属性

        /// <summary>
        /// 返回实体所在集合（如果实体包含在集合中）
        /// </summary>
        /// <returns>集合,如果不在集合中返回null</returns>
        public rbEntityCollectionBase GetCollection()
        {
            return collection;
        }

        /// <summary>
        /// 实体集合,如果实体不在集合中返回null.
        /// </summary>
        [XmlIgnore]
        internal rbEntityCollectionBase Collection
        {
            get
            {
                return collection;
            }

            set
            {
                collection = value;
            }
        }

        /// <summary>
        /// 指示该实体是否是被added, deleted, 或 modified
        /// </summary>
        public rbDataRowState RowState
        {
            get { return rowState; }
            set { rowState = value; }
        }

        /// <summary>
        /// 防止属性冲突
        /// </summary>
#if (!WindowsCE)
        [Browsable(false)]
        [Bindable(false)]
#endif
        [XmlIgnore]
        public IEntity rb
        {
            get { return this as IEntity; }
        }

        #endregion

        #region Sort

        /// <summary>
        /// 默认排序实现,可以重写对单个或多个属性提供排序.
        /// </summary>
        /// <param name="other">比较的实体</param>
        /// <param name="rbColumn">rbColumn - 扩展属性无效</param>
        /// <param name="propertyName">有效的列名</param>
        /// <returns></returns>
        virtual public int OnSort(rbEntity other, rbColumnMetadata rbColumn, string propertyName)
        {
            rbSystemType rbType = rbSystemType.Unassigned;

            string columnName = string.Empty;

            if (rbColumn == null)
            {
                // This code will only be executed for extra or extended properties
                object oThat = other.GetColumn(propertyName);
                object oThis = GetColumn(propertyName);

                if (oThat == null || oThis == null)
                {
                    return rbEntity.Compare(oThis, oThat);
                }

                columnName = propertyName;

                Type t = oThis.GetType();

                switch (t.Name)
                {
                    case "Boolean": rbType = rbSystemType.Boolean; break;
                    case "Byte": rbType = rbSystemType.Byte; break;
                    case "Char": rbType = rbSystemType.Char; break;
                    case "DateTime": rbType = rbSystemType.DateTime; break;
                    case "Decimal": rbType = rbSystemType.Decimal; break;
                    case "Double": rbType = rbSystemType.Double; break;
                    case "Guid": rbType = rbSystemType.Guid; break;
                    case "Int16": rbType = rbSystemType.Int16; break;
                    case "Int32": rbType = rbSystemType.Int32; break;
                    case "Int64": rbType = rbSystemType.Int64; break;
                    case "SByte": rbType = rbSystemType.SByte; break;
                    case "Single": rbType = rbSystemType.Single; break;
                    case "String": rbType = rbSystemType.String; break;
                    case "TimeSpan": rbType = rbSystemType.TimeSpan; break;
                    case "UInt16": rbType = rbSystemType.UInt16; break;
                    case "UInt32": rbType = rbSystemType.UInt32; break;
                    case "UInt64": rbType = rbSystemType.UInt64; break;
                 }
            }
            else
            {
                rbType = rbColumn.rbType;
                columnName = rbColumn.Name;
            }

            switch (rbType)
            {
                case rbSystemType.Boolean:
                    {
                        bool? oThat = other.GetSystemBoolean(columnName);
                        bool? oThis = GetSystemBoolean(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Byte:
                    {
                        byte? oThat = other.GetSystemByte(columnName);
                        byte? oThis = GetSystemByte(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Char:
                    {
                        char? oThat = other.GetSystemChar(columnName);
                        char? oThis = GetSystemChar(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.DateTime:
                    {
                        DateTime? oThat = other.GetSystemDateTime(columnName);
                        DateTime? oThis = GetSystemDateTime(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Decimal:
                    {
                        decimal? oThat = other.GetSystemDecimal(columnName);
                        decimal? oThis = GetSystemDecimal(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Double:
                    {
                        double? oThat = other.GetSystemDouble(columnName);
                        double? oThis = GetSystemDouble(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Guid:
                    {
                        Guid? oThat = other.GetSystemGuid(columnName);
                        Guid? oThis = GetSystemGuid(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Int16:
                    {
                        short? oThat = other.GetSystemInt16(columnName);
                        short? oThis = GetSystemInt16(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Int32:
                    {
                        int? oThat = other.GetSystemInt32(columnName);
                        int? oThis = GetSystemInt32(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Int64:
                    {
                        long? oThat = other.GetSystemInt64(columnName);
                        long? oThis = GetSystemInt64(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.SByte:
                    {
                        sbyte? oThat = other.GetSystemSByte(columnName);
                        sbyte? oThis = GetSystemSByte(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.Single:
                    {
                        float? oThat = other.GetSystemSingle(columnName);
                        float? oThis = GetSystemSingle(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.String:
                    {
                        string oThat = other.GetSystemString(columnName);
                        string oThis = GetSystemString(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.CompareTo(oThat);
                    }
                case rbSystemType.TimeSpan:
                    {
                        TimeSpan? oThat = other.GetSystemTimeSpan(columnName);
                        TimeSpan? oThis = GetSystemTimeSpan(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.UInt16:
                    {
                        ushort? oThat = other.GetSystemUInt16(columnName);
                        ushort? oThis = GetSystemUInt16(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.UInt32:
                    {
                        uint? oThat = other.GetSystemUInt32(columnName);
                        uint? oThis = GetSystemUInt16(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
                case rbSystemType.UInt64:
                    {
                        ulong? oThat = other.GetSystemUInt64(columnName);
                        ulong? oThis = GetSystemUInt64(columnName);
                        int result = rbEntity.Compare(oThis, oThat);
                        return (result != 2) ? result : oThis.Value.CompareTo(oThat.Value);
                    }
            }

            return 0;
        }

        /// <summary>
        /// OnSort方法调用，用于比较给定类型的对象.该方法不是真正比较值，而是只处理NULL值.
        /// </summary>
        /// <param name="oThis"></param>
        /// <param name="oThat"></param>
        /// <returns>如果oThis和oThat都不为null，返回2，否则0, 1,或 -1</returns>
        static protected int Compare(object oThis, object oThat)
        {
            if (oThis == null || oThat == null)
            {
                if (oThis == null && oThat == null) return 0;
                if (oThat == null) return 1;
                if (oThis == null) return -1;
            }

            return 2;
        }

        #endregion

        #region Entity Property Helpers

        //protected Dictionary<string, object> GetExtraColumnsArray()
        //{
        //    return this.GetExtraColumns();
        //}
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public List<string> GetCurrentListOfColumns()
        {
            List<string> columns = new List<string>();

            foreach (string column in currentValues.Keys)
            {
                columns.Add(column);
            }

            return columns;
        }		

        /// <summary>
        /// 如果实体包含传递的列，返回true.
        /// </summary>
        /// <param name="columnName">所需的列名</param>
        /// <returns></returns>
        public bool ContainsColumn(string columnName)
        {
            return currentValues.ContainsKey(columnName);
        }

        /// <summary>
        /// 用于在列改变之前获取原始值.也可以用于列删除后，获取原始列的值.
        /// </summary>
        /// <param name="columnName">列名 (不是属性名)</param>
        /// <returns>列的原始值</returns>
        public object GetOriginalColumnValue(string columnName)
        {
            if (this.originalValues != null && this.originalValues.ContainsKey(columnName))
            {
                return originalValues[columnName];
            }

            return null;
        }


        /// <summary>
        /// 这个调用从来不会被应用
        /// </summary>
        /// <param name="columnName">列名 (不是属性名)</param>
        /// <param name="value">设置的值</param>
        protected void SetOriginalColumnValue(string columnName, object value)
        {
            if (this.originalValues == null)
            {
                this.originalValues = new rbSmartDictionary();
            }
            
            originalValues[columnName] = value;
        }

        /// <summary>
        /// 用于绑定不在rbEntity类中的字段.
        /// </summary>
        /// <remarks>
        /// 绑定comboboxes或listboxes的时候非常有用.
        /// </remarks>
        /// <example>
        /// <code>
        /// InvoicesCollection invColl = new InvoicesCollection(); 
        /// invColl.Query.Select(invColl.Query.CustomerID, "&lt;[City] + ', ' + [Country] as SpecialBinder&gt;"); 
        /// invColl.Query.Load(); 
        /// 
        /// this.comboBox1.DataSource = invColl; 
        ///	this.comboBox1.DisplayMember = "SpecialBinder"; 
        /// this.comboBox1.ValueMember = InvoicrbMetadata.ColumnNames.CustomerID;
        /// </code>
        /// </example>
#if (!WindowsCE)
        [BrowsableAttribute(false)]
#endif
        [XmlIgnore]
        virtual public object SpecialBinder
        {
            get
            {
                if (currentValues.ContainsKey("SpecialBinder"))
                {
                    return currentValues["SpecialBinder"];
                }
                else
                {
                    return null;
                }
            }

            set
            {
                if (currentValues.ContainsKey("SpecialBinder"))
                {
                    currentValues["SpecialBinder"] = value;
                }
            }
        }

        /// <summary>
        /// 对列赋值.该方法仅用于列没有强类型属性的情况.使用扩展列自定义加载实体的时候非常有用.
        /// </summary>
        /// <param name="columnName">列名，例如"MyColumn".</param>
        /// <param name="Value">列所需的值.</param>
        /// <seealso cref="GetColumn"/>
        public void SetColumn(string columnName, object Value)
        {
            SetValue(columnName, Value);
        }

        /// <summary>
        /// 对列赋值.该方法仅用于列没有强类型属性的情况.使用扩展列自定义加载实体的时候非常有用.
        /// </summary>
        /// <param name="columnName">列名，例如"MyColumn".</param>
        /// <param name="Value">列所需的值.</param>
        /// <param name="isVirtualColumn">如果是虚拟列，设置为true.</param> 
        /// <seealso cref="GetColumn"/>
        public void SetColumn(string columnName, object Value, bool isVirtualColumn)
        {
            currentValues[columnName] = Value;

            if (!isVirtualColumn) //&& this.Meta.Columns[columnName] != null)
            {
                this.MarkFieldAsModified(columnName);
            }
        }

        /// <summary>
        /// 访问底层DataTable获取列值. 该方法仅用于列没有强类型属性的情况.使用扩展列自定义加载实体的时候非常有用.
        /// </summary>
        /// <param name="columnName">列名，例如"MyColumn".</param>
        /// <returns>返回值,需要转换成适当的类型.</returns>
        /// <seealso cref="SetColumn"/>
        public object GetColumn(string columnName)
        {
            if (currentValues == null || currentValues.Count == 0 || !currentValues.ContainsKey(columnName) || rowState == rbDataRowState.Deleted)
            {
                if (rowState == rbDataRowState.Added && !applyDefaultsCalled)
                {
                    applyDefaultsCalled = true;
                    ApplyDefaults();
                }

                return null;
            }
            else
            {
                object o = currentValues[columnName];
                return (o == DBNull.Value) ? null : o;
            }
        }

        /// <summary>
        /// 访问底层DataTable获取列值. 该方法仅用于列没有强类型属性的情况.使用扩展列自定义加载实体的时候非常有用.
        /// </summary>
        /// <param name="columnName">列名，例如"MyColumn".</param>
        /// <param name="defaultIfNull">列为null的时候，默认返回的值</param>
        /// <returns>返回值, 如果列为null的时候,返回defaultIfNull</returns>
        public object GetColumn(string columnName, object defaultIfNull)
        {
            object temp = GetColumn(columnName);
            if (temp == null)
            {
                return defaultIfNull;
            }

            return temp;
        }

        #region Row Accessors

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">行中的列名</param>
        protected System.Object GetSystemObject(string columnName)
        {
            if (!FieldsExists(this)) return null;

            if (currentValues.ContainsKey(columnName))
            {
                object o = currentValues[columnName];
                return (o == DBNull.Value) ? null : (System.Object)o;
            }
            else return null;
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemObject(string columnName, System.Object data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Int16? GetSystemInt16(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == DBNull.Value)
                return null;
            else
                return (o is System.Int16) ? (System.Int16?)o : Convert.ToInt16(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Int16 GetSystemInt16Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Int16) ? (System.Int16)o : Convert.ToInt16(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemInt16(string columnName, System.Int16? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.Int32? GetSystemInt32(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if(o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Int32) ? (System.Int32?)o : Convert.ToInt32(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Int32 GetSystemInt32Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Int32) ? (System.Int32)o : Convert.ToInt32(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemInt32(string columnName, System.Int32? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.Int64? GetSystemInt64(string columnName)
        {
            if (!FieldsExists(this)) return null; ;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Int64) ? (System.Int64?)o : Convert.ToInt64(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Int64 GetSystemInt64Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Int64) ? (System.Int64)o : Convert.ToInt64(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemInt64(string columnName, System.Int64? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        [CLSCompliant(false)]
        protected System.UInt16? GetSystemUInt16(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.UInt16) ? (System.UInt16?)o : Convert.ToUInt16(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        [CLSCompliant(false)]
        protected System.UInt16 GetSystemUInt16Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.UInt16) ? (System.UInt16)o : Convert.ToUInt16(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        [CLSCompliant(false)]
        protected bool SetSystemUInt16(string columnName, System.UInt16? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        [CLSCompliant(false)]
        protected System.UInt32? GetSystemUInt32(string columnName)
        {
            if (!FieldsExists(this)) return null; ;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.UInt32) ? (System.UInt32?)o : Convert.ToUInt32(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        [CLSCompliant(false)]
        protected System.UInt32 GetSystemUInt32Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.UInt32) ? (System.UInt32)o : Convert.ToUInt32(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        [CLSCompliant(false)]
        protected bool SetSystemUInt32(string columnName, System.UInt32? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        [CLSCompliant(false)]
        protected System.UInt64? GetSystemUInt64(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.UInt64) ? (System.UInt64?)o : Convert.ToUInt64(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        [CLSCompliant(false)]
        protected System.UInt64 GetSystemUInt64Required(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.UInt64) ? (System.UInt64)o : Convert.ToUInt64(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        [CLSCompliant(false)]
        protected bool SetSystemUInt64(string columnName, System.UInt64? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Boolean? GetSystemBoolean(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Boolean) ? (System.Boolean?)o : Convert.ToBoolean(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Boolean GetSystemBooleanRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Boolean) ? (System.Boolean)o : Convert.ToBoolean(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemBoolean(string columnName, System.Boolean? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.Char? GetSystemChar(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Char) ? (System.Char?)o : Convert.ToChar(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值System.Char
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Char GetSystemCharRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Char) ? (System.Char)o : Convert.ToChar(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemChar(string columnName, System.Char? data)
        {
            return SetValueChar(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.String GetSystemString(string columnName)
        {
            if(!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.String) ? (System.String)o : o.ToString();
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.String GetSystemStringRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.String) ? (System.String)o : o.ToString();
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemString(string columnName, System.String data)
        {
            if (rbEntity.ConvertEmptyStringToNull == true && data != null && data.Length == 0)
            {
                data = null;
            }

            return SetValue(columnName, data);
        }

        /// <summary>
        /// rb2009临时解决办法.将String.Empty转换为NULL 
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemString2(string columnName, System.String data)
        {
            if (data != null && data.Length == 0)
                data = null;

            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Decimal? GetSystemDecimal(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Decimal) ? (System.Decimal?)o : Convert.ToDecimal(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Decimal GetSystemDecimalRequired(string columnName)
        {
            object o = null;
            currentValues.TryGetValue(columnName, out o);
            return (o is System.Decimal) ? (System.Decimal)o : Convert.ToDecimal(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemDecimal(string columnName, System.Decimal? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Double? GetSystemDouble(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Double) ? (System.Double?)o : Convert.ToDouble(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Double GetSystemDoubleRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Double) ? (System.Double)o : Convert.ToDouble(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemDouble(string columnName, System.Double? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.DateTime? GetSystemDateTime(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.DateTime) ? (System.DateTime?)o : Convert.ToDateTime(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.DateTime GetSystemDateTimeRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.DateTime) ? (System.DateTime)o : Convert.ToDateTime(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemDateTime(string columnName, System.DateTime? data)
        {
            return SetValue(columnName, data);
        }

#if (!WindowsCE)

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.DateTimeOffset? GetSystemDateTimeOffset(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (System.DateTimeOffset?)o;
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.DateTimeOffset GetSystemDateTimeOffsetRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (System.DateTimeOffset)o;
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemDateTimeOffset(string columnName, System.DateTimeOffset? data)
        {
            return SetValue(columnName, data);
        }

#endif

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.TimeSpan? GetSystemTimeSpan(string columnName)
        {
            if (!FieldsExists(this)) return null; ;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (System.TimeSpan)o;
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.TimeSpan GetSystemTimeSpanRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (System.TimeSpan)o;
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemTimeSpan(string columnName, System.TimeSpan? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.Byte? GetSystemByte(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Byte) ? (System.Byte?)o : Convert.ToByte(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Byte GetSystemByteRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Byte) ? (System.Byte)o : Convert.ToByte(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemByte(string columnName, System.Byte? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        [CLSCompliant(false)]
        protected System.SByte? GetSystemSByte(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.SByte) ? (System.SByte?)o : Convert.ToSByte(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        [CLSCompliant(false)]
        protected System.SByte GetSystemSByteRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.SByte) ? (System.SByte)o : Convert.ToSByte(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        [CLSCompliant(false)]
        protected bool SetSystemSByte(string columnName, System.SByte? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Guid? GetSystemGuid(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Guid) ? (System.Guid?)o : new Guid((string)o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName"></param>
        /// <returns></returns>
        protected System.Guid GetSystemGuidRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Guid) ? (System.Guid)o : new Guid((string)o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemGuid(string columnName, System.Guid? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        protected System.Single? GetSystemSingle(string columnName)
        {
            if (!FieldsExists(this)) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return (o is System.Single) ? (System.Single?)o : Convert.ToSingle(o);
        }

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <returns></returns>
        protected System.Single GetSystemSingleRequired(string columnName)
        {
            object o = null;
            if (FieldsExistsRequired(this))
            {
                currentValues.TryGetValue(columnName, out o);
            }
            return (o is System.Single) ? (System.Single)o : Convert.ToSingle(o);
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        protected bool SetSystemSingle(string columnName, System.Single? data)
        {
            return SetValue(columnName, data);
        }

        /// <summary>
        /// 所有"char"类型的属性可以调用
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        /// <returns>如果设置成功，返回true</returns>
        private bool SetValueChar(string columnName, object data)
        {
            bool changed = true;

            if (rowState == rbDataRowState.Deleted) throw new Exception("无法修改已删除的记录");

            try
            {
                if (currentValues == null)
                {
                    currentValues = new rbSmartDictionary();
                    CurrentValues_OnFirstAccess(currentValues);
                }

                if (currentValues.Count == 0)
                {
                    if (rowState == rbDataRowState.Added && !applyDefaultsCalled)
                    {
                        applyDefaultsCalled = true;
                        ApplyDefaults();
                    }
                }

                if (!currentValues.ContainsKey(columnName))
                {
                    currentValues[columnName] = data;
                    changed = true;

                    if (rowState == rbDataRowState.Unchanged)
                    {
                        rowState = rbDataRowState.Modified;
                    }
                }
                else
                {
                    object o = currentValues[columnName];
                    bool isNull = (o == DBNull.Value || o == null);

                    // Char type hack, ADO.NET often returns them as a string
                    if (!isNull && data.GetType().ToString() == typeof(char).ToString() && typeof(string).ToString() == o.GetType().ToString())
                    {
                        string str = o as string;

                        if (str != null && str.Length == 1)
                        {
                            o = str[0];
                        }
                    }

                    // Note that we grab this before we make the change
                    rbDataRowState state = rowState;

                    if (data == null && isNull)
                    {
                        // Nothing to do here
                    }
                    else
                    {
                        if (isNull && data != null)
                            currentValues[columnName] = data;
                        else if (data == null && !isNull)
                            currentValues[columnName] = DBNull.Value;
                        else if (!o.Equals(data))
                        {
                            this.currentValues[columnName] = data;

                            // Special logic to see if we have changed it back to it's original value, if 
                            // so we mark this column as no longer dirty, which if the only one could return
                            // the rowstate back to "Unchanged"
                            if (originalValues != null && originalValues.ContainsKey(columnName))
                            {
                                if (data == originalValues[columnName])
                                {
                                    MarkFieldAsUnchanged(columnName);
                                    return true; // it still changed but we don't want to mark it as dirty
                                }
                            }
                        }
                        else
                            changed = false;
                    }
                }

                if (changed)
                {
                    MarkFieldAsModified(columnName);
                }
            }
            finally
            {

            }

            return changed;
        }

        /// <summary>
        /// 所有的属性可以调用
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="data">设置的值</param>
        /// <returns>如果设置成功，返回true</returns>
        private bool SetValue(string columnName, object data)
        {
            bool changed = true;

            if (rowState == rbDataRowState.Deleted) throw new Exception("不能修改已删除的记录");

            try
            {
                if (currentValues == null)
                {
                    currentValues = new rbSmartDictionary();
                    CurrentValues_OnFirstAccess(currentValues);
                }

                if (currentValues.Count == 0)
                {
                    if (rowState == rbDataRowState.Added && !applyDefaultsCalled)
                    {
                        applyDefaultsCalled = true;
                        ApplyDefaults();
                    }
                }

                if (!currentValues.ContainsKey(columnName))
                {
                    currentValues[columnName] = data;
                    changed = true;

                    if (rowState == rbDataRowState.Unchanged)
                    {
                        rowState = rbDataRowState.Modified;
                    }
                }
                else
                {
                    object o = currentValues[columnName];
                    bool isNull = (o == DBNull.Value || o == null);

                    // Note that we grab this before we make the change
                    rbDataRowState state = rowState;

                    if (data == null && isNull)
                    {
                        // Nothing to do here
                        changed = false;
                    }
                    else
                    {
                        if (isNull && data != null)
                            currentValues[columnName] = data;
                        else if (data == null && !isNull)
                            currentValues[columnName] = DBNull.Value;
                        else if (!o.Equals(data))
                        {
                            this.currentValues[columnName] = data;

                            // Special logic to see if we have changed it back to it's original value, if 
                            // so we mark this column as no longer dirty, which if the only one could return
                            // the rowstate back to "Unchanged"
                            if (originalValues != null && originalValues.ContainsKey(columnName))
                            {
                                if (data == originalValues[columnName])
                                {
                                    MarkFieldAsUnchanged(columnName);
                                    return true; // it still changed but we don't want to mark it as dirty
                                }
                            }
                        }
                        else
                            changed = false;
                    }
                }

                if (changed)
                {
                    MarkFieldAsModified(columnName);
                }
            }
            finally
            {

            }

            return changed;
        }

        static private bool FieldsExists(rbEntity entity)
        {
            if (entity.currentValues == null || entity.currentValues.Count == 0)
            {
                if (entity.rowState == rbDataRowState.Added && !entity.applyDefaultsCalled)
                {
                    entity.applyDefaultsCalled = true;
                    entity.ApplyDefaults();

                    if (entity.currentValues != null)
                        return true; 
                }

                return false;
            }

            return true;
        }

        static private bool FieldsExistsRequired(rbEntity entity)
        {
            if (entity.currentValues == null || entity.currentValues.Count == 0)
            {
                if (entity.rowState == rbDataRowState.Added && !entity.applyDefaultsCalled)
                {
                    entity.applyDefaultsCalled = true;
                    entity.ApplyDefaults();

                    if (entity.currentValues != null)
                        return true; 
                }

                return false;
            }

            return true;
        }

        #endregion

        #region Array Row Accessors

        /// <summary>
        /// 内部使用,获取行中特定列特定类型的值
        /// </summary>
        /// <param name="columnName">列名 in the row</param>
        protected System.Byte[] GetSystemByteArray(string columnName)
        {
            if (currentValues == null) return null;

            object o = null;
            currentValues.TryGetValue(columnName, out o);

            if (o == null || o == DBNull.Value)
                return null;
            else
                return o as byte[];
        }

        /// <summary>
        /// 内部使用，以指定类型的值为行内特定列赋值
        /// </summary>
        /// <param name="columnName">列名</param>
        /// <param name="byteArray">设置的值</param>
        protected bool SetSystemByteArray(string columnName, System.Byte[] byteArray)
        {
            MarkFieldAsModified(columnName);
            currentValues[columnName] = byteArray;
            return true;
        }
        #endregion

        #endregion

        #region MarkAs Methods ...

        /// <summary>
        /// 标记列状态为修改
        /// </summary>
        /// <param name="columnName">列名</param>
        protected void MarkFieldAsModified(string columnName)
        {
            if (this.m_modifiedColumns == null)
            {
                m_modifiedColumns = new List<string>();
            }

            if (!m_modifiedColumns.Contains(columnName))
            {
                m_modifiedColumns.Add(columnName);

                if (rowState != rbDataRowState.Added)
                {
                    rowState = rbDataRowState.Modified;
                }
            }
        }

        /// <summary>
        /// 移除修改状态
        /// </summary>
        /// <param name="columnName">需要清除状态的列名</param>
        protected void MarkFieldAsUnchanged(string columnName)
        {
            if (this.m_modifiedColumns == null) return;

            if (m_modifiedColumns.Contains(columnName))
            {
                m_modifiedColumns.Remove(columnName);

                if (m_modifiedColumns.Count == 0)
                {
                    AcceptChanges();
                }
            }
        }

        /// <summary>
        /// 将实体对应的DataRow中所有的列标记为指定状态.
        /// </summary>
        /// <remarks>
        /// 下面的例子展示了对于同一个rbEntity对象，使用MarkAllColumnsAsDirty从一个数据库读取数据然后写入到另外一个数据库.
        /// <code>
        /// Customer c = new Customer(); 
        /// c.LoadByPrimaryKey(5);   //从默认的Microsoft SQL连接
        /// c.MarkAllColumnsAsDirty(DataRowState.Added); 
        /// c.rb.Connection.Name = "Oracle"; //重写连接信息
        /// c.Save();                // 保存到Oracle数据库
        /// </code>
        /// 只支持DataRowSate.Added和DataRowState.Modifed.
        /// DataRowState.Deleted不能调用这个. 使用entity.MarkAsDeleted()代替.
        /// </remarks>
        /// <param name="state">The DataRowState enumeration to which the DataRow of the entity is set.</param>
        public void MarkAllColumnsAsDirty(rbDataRowState state)
        {
            (this as IEntity).RowState = state;

            foreach (rbColumnMetadata meta in this.Meta.Columns)
            {
                MarkFieldAsModified(meta.Name);
            }
        }

        /// <summary>
        /// 标记实体状态为deleted,如果保存，实体将从数据库中被删除.
        /// </summary>
        virtual public void MarkAsDeleted()
        {
            if (rowState == rbDataRowState.Deleted) return;

            if (collection != null)
            {
                IList list = collection as IList;
                if (list.Contains(this))
                {
                    list.Remove(this);
                }

                if (this.RowState != rbDataRowState.Added)
                {
                    collection.AddEntityToDeletedList(this);
                }
            }

            if (this.RowState == rbDataRowState.Added)
            {
                try
                {
                    foreach (rbColumnMetadata esCol in this.Meta.Columns)
                    {
                        if (!esCol.IsInPrimaryKey)
                        {
                            this.SetColumn(esCol.Name, null);
                        }
                    }
                }
                catch { }

                rowState = rbDataRowState.Unchanged;
            }
            else
            {
                rowState = rbDataRowState.Deleted;
            }
        }

        #endregion

        #region Accept / Reject Changes

        /// <summary>
        /// 接受所有变更.将状态标记为Unchanged，请参阅<see cref="RejectChanges"/>
        /// </summary>
        virtual public void AcceptChanges()
        {
            if (rowState == rbDataRowState.Deleted)
            {
                currentValues = originalValues = null;
                m_modifiedColumns = null;
                rowState = rbDataRowState.Invalid;
            }
            else
            {
                originalValues = new rbSmartDictionary(currentValues);
                rowState = rbDataRowState.Unchanged;
                m_modifiedColumns = null;
            }
        }

        /// <summary>
        /// RejectChanges正好与 <see cref="AcceptChanges"/>相反. RejectChanges将原始值返回到当前值，相当于没有发生任何改变.
        /// </summary>
        /// <seealso cref="AcceptChanges"/>
        virtual public void RejectChanges()
        {
            if (rowState == rbDataRowState.Added)
            {
                currentValues = new rbSmartDictionary(currentValues.Count);
                rowState = rbDataRowState.Unchanged;
                m_modifiedColumns = null;
            }
            else
            {
                currentValues = new rbSmartDictionary(originalValues);
                rowState = rbDataRowState.Unchanged;
                m_modifiedColumns = null;
            }
        }

        #endregion

        #region Save
        /// <summary>
        /// 保存实体.
        /// </summary>
        /// <remarks>
        /// 保存总是在一个事务中.你不需要使用事务除非你需要保存两个不同的对象:例如Employees 和 Products.
        /// </remarks>
        /// <example>
        /// <code>
        /// Employees entity = new Employees();
        /// entity.LoadByPrimaryKey(32);
        /// entity.MarkAsDeleted();
        /// entity.Save();
        /// </code>
        /// </example>
        /// <seealso cref="MarkAsDeleted"/>
        virtual public void Save()
        {
            IEntity entity = this as IEntity;
            this.Save(entity.Connection.SqlAccessType);
        }

        /// <summary>
        /// 使用指定的SqlAccessType保存实体. 该方法主要用于覆盖配置文件中值的时候.
        /// </summary>
        /// <remarks>
        /// 保存总是在一个事务中.你不需要使用事务除非你需要保存两个不同的对象:例如Employees 和 Products.
        /// </remarks>
        /// <example>
        /// <code>
        /// Employees entity = new Employees();
        /// entity.FirstName = this.txtFirstName.Text;
        /// entity.LastName = this.txtLastName.Text;
        /// entity.Save(rbSqlAccessType.StoredProcedure);
        /// </code>
        /// </example>
        /// <param name="sqlAccessType">See <see cref="rbSqlAccessType"/>.</param>
        virtual public void Save(rbSqlAccessType sqlAccessType)
        {
            if (!NeedsTransactionDuringSave())
            {
                // Save modified or added rows only
                if (rowState == rbDataRowState.Modified || rowState == rbDataRowState.Added)
                {
                    this.SaveToProvider(sqlAccessType);
                }

                // Save my deleted records on the way back up
                if (rowState == rbDataRowState.Deleted)
                {
                    this.SaveToProvider(sqlAccessType);
                }

                this.AcceptChanges();
            }
            else
            {
                rbTransactionScopeOption txOption =
                    rbTransactionScope.GetCurrentTransactionScopeOption() == rbTransactionScopeOption.Suppress ?
                    rbTransactionScopeOption.Suppress : rbTransactionScopeOption.Required;

                using (rbTransactionScope scope = new rbTransactionScope(txOption))
                {
                    // 1) Commit the PreSaves
                    this.CommitPreSaves();
                    this.ApplyPreSaveKeys();

                    // 2) Save me ...  (modified or added rows only)
                    if (rowState == rbDataRowState.Modified || rowState == rbDataRowState.Added)
                    {
                        this.SaveToProvider(sqlAccessType);
                    }

                    // 3) Commit the PostSaves
                    this.ApplyPostSaveKeys();
                    this.ApplyPostOneSaveKeys();
                    this.CommitPostSaves();
                    this.CommitPostOneSaves();

                    // 4) Save my deleted records on the way back up
                    if (rowState == rbDataRowState.Deleted)
                    {
                        this.SaveToProvider(sqlAccessType);
                    }

                    this.AcceptChanges();

                    scope.Complete();
                }
            }
        }

        /// <summary>
        /// 生成的类重写，用于处理分层保存逻辑的时候.
        /// </summary>
        /// <seealso cref="ApplyPostSaveKeys"/>
        virtual internal protected void ApplyPreSaveKeys()
        {

        }

        /// <summary>
        /// 生成的类重写，用于处理分层保存逻辑的时候.
        /// </summary>
        /// <seealso cref="ApplyPreSaveKeys"/> 
        virtual internal protected void ApplyPostSaveKeys()
        {

        }

        /// <summary>
        ///生成的类重写，用于处理分层保存逻辑的时候.
        /// </summary>
        /// <seealso cref="ApplyPreSaveKeys"/> 
        virtual internal protected void ApplyPostOneSaveKeys()
        {

        }

        /// <summary>
        /// 数据访问器上的rbSaveDataTable调用，用于物理保存数据.
        /// </summary>
        /// <param name="sqlAccessType"></param>
        /// <seealso cref="Save"/>
        virtual protected void SaveToProvider(rbSqlAccessType sqlAccessType)
        {
            rbDataRequest request = CreateRequest();

            #region Auditing fields
            rbColumnMetadataCollection cols = this.Meta.Columns;

            if (rowState == rbDataRowState.Added)
            {
                if (cols.DateAdded != null && cols.DateAdded.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateAdded.ColumnName, cols.DateAdded.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.AddedBy != null && cols.AddedBy.UseEventHandler && AddedByEventHandler != null)
                {
                    this.SetColumn(cols.AddedBy.ColumnName, AddedByEventHandler(), false);
                }

                if (cols.DateModified != null && cols.DateModified.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateModified.ColumnName, cols.DateModified.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.ModifiedBy != null && cols.ModifiedBy.UseEventHandler && ModifiedByEventHandler != null)
                {
                    this.SetColumn(cols.ModifiedBy.ColumnName, ModifiedByEventHandler(), false);
                }
            }
            else if (rowState == rbDataRowState.Modified)
            {
                if (cols.DateModified != null && cols.DateModified.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateModified.ColumnName, cols.DateModified.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.ModifiedBy != null && cols.ModifiedBy.UseEventHandler && ModifiedByEventHandler != null)
                {
                    this.SetColumn(cols.ModifiedBy.ColumnName, ModifiedByEventHandler(), false);
                }
            }
            #endregion

            request.EntitySavePacket.Entity = this;
            request.EntitySavePacket.OriginalValues = originalValues;
            request.EntitySavePacket.CurrentValues = currentValues;
            request.EntitySavePacket.RowState = rowState;
            request.EntitySavePacket.ModifiedColumns = rb.ModifiedColumns;

            request.Columns = Meta.Columns;
            request.SqlAccessType = sqlAccessType;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.rbSaveDataTable(request, rb.Connection.ProviderSignature);

            if (response.IsException)
            {
                rowError = response.Exception.Message;

                // Game over, we received an exception
                throw response.Exception;
            }
        }

        internal void PrepareSpecialFields()
        {
            rbColumnMetadataCollection cols = this.Meta.Columns;

            if (rowState == rbDataRowState.Added)
            {
                if (cols.DateAdded != null && cols.DateAdded.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateAdded.ColumnName, cols.DateAdded.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.AddedBy != null && cols.AddedBy.UseEventHandler && AddedByEventHandler != null)
                {
                    this.SetColumn(cols.AddedBy.ColumnName, AddedByEventHandler(), false);
                }

                if (cols.DateModified != null && cols.DateModified.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateModified.ColumnName, cols.DateModified.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.ModifiedBy != null && cols.ModifiedBy.UseEventHandler && ModifiedByEventHandler != null)
                {
                    this.SetColumn(cols.ModifiedBy.ColumnName, ModifiedByEventHandler(), false);
                }
            }
            else if (rowState == rbDataRowState.Modified)
            {
                if (cols.DateModified != null && cols.DateModified.Type == DateType.ClientSide)
                {
                    this.SetColumn(cols.DateModified.ColumnName, cols.DateModified.ClientType == ClientType.Now ? DateTime.Now : DateTime.UtcNow, false);
                }

                if (cols.ModifiedBy != null && cols.ModifiedBy.UseEventHandler && ModifiedByEventHandler != null)
                {
                    this.SetColumn(cols.ModifiedBy.ColumnName, ModifiedByEventHandler(), false);
                }
            }
        }

        #endregion

        #region Load

#if (LINQ)
        /// <summary>
        /// 允许使用LinqToSql加载实体
        /// </summary>
        /// <param name="context">System.Data.Linq.DataContext</param>
        /// <param name="query">LINQ查询</param>
        /// <returns>如果记录加载了，返回true</returns>
        /// <remarks>
        /// 下面的例子展示了使用LINQ查询加载一个实体.
        /// <code>
        /// DataContext context = new DataContext("User ID=sa;Initial Catalog=Northwind;Data Source=localhost;"); 
        ///
        /// var linqQuery = context.GetTable&lt;Employees&gt;().Where(s => s.LastName == "Griffin");
        /// 
        /// Employee emp = new Employee();
        /// if(emp.Load(context, linqQuery))
        /// {
        ///     // 查询到记录
        /// }
        /// </code>
        /// </remarks>
        virtual public bool Load(DataContext context, IQueryable query)
        {
            rbDataRequest request = this.CreateRequest();

            request.LinqContext = context;
            request.LinqQuery = query;
            request.QueryType = rbQueryType.IQueryable;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.rbLoadDataTable(request, this.rb.Connection.ProviderSignature);

            return this.PopulateEntity(response.Table);
        }
#endif

        /// <summary>
        /// 自定义加载实体. <see cref="rbQueryType"/> 提供了多种方式. 
        /// </summary>
        /// <remarks>
        /// 下面的例子展示了使用原始SQL加载实体.但这不是推荐的方式.更好的方式是使用视图或存储过程.
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public bool CustomLoad(string whereClause)
        ///     {
        ///			string sqlText = String.Empty;
        /// 
        ///         sqlText = "SELECT [LastName], [DepartmentID], [HireDate] ";
        ///         sqlText += "FROM [Employees] ";
        ///         sqlText += whereClause;
        /// 
        ///         return this.Load(rbQueryType.Text, sqlText);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <returns>如果加载完数据则返回true.</returns>
        protected bool Load(rbQueryType queryType, string query)
        {
            return Load(queryType, query, null as rbParameters);
        }

        /// <summary>
        /// 自定义加载实体. <see cref="rbQueryType"/> 提供了多种方式. 
        /// </summary>
        /// <remarks>
        /// 下面的例子展示了使用存储过程加载实体.
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public bool CustomLoad()
        ///     {
        ///         // The stored procedures expects three parameters
        ///         return this.Load(rbQueryType.StoredProcedure, "sp_MyProc", "Joe", "Smith", 27.53);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <param name="parameters">参数列表.不能带类似@ 或 ? 或别的数据库可能需要的前缀.</param>
        /// <returns>如果加载完数据则返回true.</returns>
        /// <seealso cref="rbQueryType"/>
        /// <seealso cref="rbParameters"/>
        protected bool Load(rbQueryType queryType, string query, params object[] parameters)
        {
            return Load(queryType, query, PackageParameters(parameters));
        }

        /// <summary>
        /// 自定义加载实体. <see cref="rbQueryType"/> 提供了多种方式. 
        /// </summary>
        /// <remarks>
        /// 下面的例子展示了使用存储过程加载实体.
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public bool CustomLoad()
        ///     {
        ///         rbParameters esParams = new rbParameters();   
        ///         esParams.Add("FirstName", "Joe");   
        ///         esParams.Add("LastName", "Smith");   
        ///         esParams.Add("Salary", 27.53);   
        /// 
        ///			return this.Load(rbQueryType.StoredProcedure, "sp_MyProc", esParams);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <param name="parms">参数列表. 请参阅 <see cref="rbParameters"/>.</param>
        /// <returns>如果加载完数据则返回true.</returns>
        /// <seealso cref="rbQueryType"/>
        /// <seealso cref="rbParameters"/>/// 
        protected bool Load(rbQueryType queryType, string query, rbParameters parms)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parms;
            request.QueryText = query;
            request.QueryType = queryType;

            rbConnection conn = this.rb.Connection;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.rbLoadDataTable(request, conn.ProviderSignature);

            return this.PopulateEntity(response.Table);
        }


        /// <summary>
        /// 对rbEntity绑定DataRow的时候内部调用.
        /// </summary>
        /// <remarks>
        /// 如果实体包含超过一行数据，抛出异常.
        /// </remarks>
        /// <example>
        /// <code>
        /// </code>
        /// </example>
        /// <param name="table">表名.</param>
        /// <returns>如果实体加载了，返回true.</returns>
        /// <seealso cref="HasData"/>
        protected bool PopulateEntity(DataTable table)
        {
            bool found = false;

            int count = table.Rows.Count;

            if (count > 1)
            {
                throw new Exception("一个实体只能对于一行数据");
            }

            if (count == 1)
            {
                rbColumnMetadataCollection esCols = Meta.Columns;
                rbColumnMetadata esCol;
                string columnName;
                selectedColumns = new Dictionary<string, int>();

                // Now let's actually created an rbEntity for each DataRow and thereby populate
                // the collection
                DataRow row = table.Rows[0];
                DataColumnCollection cols = table.Columns;

                Dictionary<string, int> ordinals = new Dictionary<string, int>(cols.Count);
                foreach (DataColumn col in cols)
                {
                    // Let's make sure we use the Case in the Metadata Class, if they return "employeeid" in a proc
                    // this little trick will make sure we use "EmployeeId" for our property accessors
                    esCol = esCols.FindByColumnName(col.ColumnName);
                    columnName = esCol != null ? esCol.Name : col.ColumnName;

                    ordinals[columnName] = col.Ordinal;

                    if (esCol != null)
                    {
                        selectedColumns[columnName] = 0;
                    }
                }

                object[] values = row.ItemArray;

                currentValues = new rbSmartDictionary(ordinals, values);
                originalValues = new rbSmartDictionary(ordinals, values, true);
                if (m_modifiedColumns != null) m_modifiedColumns = null;
                rowState = rbDataRowState.Unchanged;

                found = true;
            }

            return found;
        }

        #endregion

        #region ExecuteNonQuery

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate(string newName, int empID)
        ///     {
        ///			string sqlText = String.Empty;
        /// 
        ///         sqlText = "UPDATE [Employees] ";
        ///         sqlText += "SET [LastName] = '" + newName + "' ";
        ///         sqlText += "WHERE [EmployeeID] = " + empID;
        /// 
        ///         return this.ExecuteNonQuery(rbQueryType.Text, sqlText);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <returns>影响的行数.</returns>
        /// <seealso cref="rbQueryType"/>
        protected int ExecuteNonQuery(rbQueryType queryType, string query)
        {
            return ExecuteNonQuery(queryType, query, null as rbParameters);
        }

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate(string newName, int empID)
        ///     {
        ///			string sqlText = String.Empty;
        /// 
        ///         sqlText = "UPDATE [Employees] ";
        ///         sqlText += "SET [LastName] = {0} ";
        ///         sqlText += "WHERE [EmployeeID] = {1}";
        /// 
        ///         return this.ExecuteNonQuery(rbQueryType.Text, sqlText, newName, empID);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <param name="parameters">A list of parameters.</param>
        /// <returns>影响的行数.</returns>
        protected int ExecuteNonQuery(rbQueryType queryType, string query, params object[] parameters)
        {
            return ExecuteNonQuery(queryType, query, PackageParameters(parameters));
        }

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate(string newName)
        ///     {
        ///			string sqlText = String.Empty;
        ///			rbParameters esParams = new rbParameters();
        ///			esParams.Add("FirstName", newName);
        ///			esParams.Add("LastName", "Doe");
        ///			esParams.Add("Salary", 27.53);
        /// 
        ///         sqlText = "UPDATE [Employees] ";
        ///			sqlText += "SET [FirstName] =  @FirstName ";
        ///			sqlText += "WHERE [LastName] = @LastName ";
        ///			sqlText += "AND [Salary] = @Salary";
        /// 
        ///         return this.ExecuteNonQuery(rbQueryType.Text, sqlText, esParams);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="queryType">请参阅 <see cref="rbQueryType"/>.</param>
        /// <param name="query">SQL语句或存储过程名称.</param>
        /// <param name="parms">A list of parameters. See <see cref="rbParameters"/>.</param>
        /// <returns>影响的行数.</returns>
        protected int ExecuteNonQuery(rbQueryType queryType, string query, rbParameters parms)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parms;
            request.QueryText = query;
            request.QueryType = queryType;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteNonQuery(request, this.rb.Connection.ProviderSignature);

            return response.RowsEffected;
        }

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate()
        ///     {
        ///			return this.ExecuteNonQuery(this.rb.Schema, "MyStoredProc");
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="schema">See <see cref="IEntity.Schema"/>.</param>
        /// <param name="storedProcedure">The name of a stored procedure.</param>
        /// <returns>影响的行数.</returns>
        protected int ExecuteNonQuery(string schema, string storedProcedure)
        {
            return ExecuteNonQuery(schema, storedProcedure, null as rbParameters);
        }

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate(string newName, int empID)
        ///     {
        ///			return this.ExecuteNonQuery(this.rb.Schema, "MyStoredProc", newName, empID);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="schema">See <see cref="IEntity.Schema"/>.</param>
        /// <param name="storedProcedure">The name of a stored procedure.</param>
        /// <param name="parameters">A list of parameters.</param>
        /// <returns>影响的行数.</returns>
        protected int ExecuteNonQuery(string schema, string storedProcedure, params object[] parameters)
        {
            return ExecuteNonQuery(schema, storedProcedure, PackageParameters(parameters));
        }

        /// <summary>
        /// 对连接执行Transact-SQL 语句并返回受影响的行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteNonQuery
        /// </remarks>
        /// <example>
        /// <code>
        /// public partial class Employees : esEmployees
        /// {
        ///     public int CustomUpdate(string newName)
        ///     {
        ///			rbParameters esParams = new rbParameters();
        ///			esParams.Add("FirstName", newName);
        ///			esParams.Add("LastName", "Doe");
        ///			esParams.Add("Salary", 27.53);
        /// 
        ///			return this.ExecuteNonQuery(this.rb.Schema, "MyStoredProc", esParams);
        ///     }
        /// }
        /// </code>
        /// </example>
        /// <param name="schema">See <see cref="IEntity.Schema"/>.</param>
        /// <param name="storedProcedure">The name of a stored procedure.</param>
        /// <param name="parameters">A list of parameters. See <see cref="rbParameters"/>.</param>
        /// <returns>影响的行数.</returns>
        protected int ExecuteNonQuery(string schema, string storedProcedure, rbParameters parameters)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parameters;
            request.Schema = schema;
            request.QueryText = storedProcedure;
            request.QueryType = rbQueryType.StoredProcedure;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteNonQuery(request, this.rb.Connection.ProviderSignature);

            return response.RowsEffected;
        }

        #endregion

        #region ExecuteReader

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader. 
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>The IDataReader</returns>
        protected IDataReader ExecuteReader(rbQueryType queryType, string query)
        {
            return ExecuteReader(queryType, query, null as rbParameters);
        }

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>ExecuteReader.</returns>
        protected IDataReader ExecuteReader(rbQueryType queryType, string query, params object[] parameters)
        {
            return ExecuteReader(queryType, query, PackageParameters(parameters));
        }

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// <code>
        /// public MyCollection : esMyCollection
        /// {
        /// 	public IDataReader CustomExecuteReader()
        /// 	{
        /// 		// 存储过程"proc_GetByLastName"需要LastName参数.注意不能使用 @, 或 :, 或 ? 或别的前缀类型，RobinLightNing可以根据数据库自动加上对应的前缀.
        /// 		rbParameters esParams = new rbParameters();			
        /// 		esParams.Add("LastName", "Doe");
        /// 			
        /// 		return this.ExecuteReader(rbQueryType.StoredProcedure, "proc_GetByLastName", esParams);
        ///		}
        /// }
        /// </code> 
        /// </example>
        /// <returns>ExecuteReader.</returns>
        protected IDataReader ExecuteReader(rbQueryType queryType, string query, rbParameters parms)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parms;
            request.QueryText = query;
            request.QueryType = queryType;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteReader(request, this.rb.Connection.ProviderSignature);

            return response.DataReader;
        }

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>ExecuteReader.</returns>
        protected IDataReader ExecuteReader(string schema, string storedProcedure)
        {
            return ExecuteReader(schema, storedProcedure, null as rbParameters);
        }

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>ExecuteReader.</returns>
        protected IDataReader ExecuteReader(string schema, string storedProcedure, params object[] parameters)
        {
            return ExecuteReader(schema, storedProcedure, PackageParameters(parameters));
        }

        /// <summary>
        /// 自定义的rbEntity或rbEntityCollection可以调用.不可以填充实体.请请参阅<see cref="rbLoadData"/>
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteReader.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>ExecuteReader.</returns>
        protected IDataReader ExecuteReader(string schema, string storedProcedure, rbParameters parameters)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parameters;
            request.Schema = schema;
            request.QueryText = storedProcedure;
            request.QueryType = rbQueryType.StoredProcedure;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteReader(request, this.rb.Connection.ProviderSignature);

            return response.DataReader;
        }

        #endregion

        #region ExecuteScalar

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(rbQueryType queryType, string query)
        {
            return ExecuteScalar(queryType, query, null as rbParameters);
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(rbQueryType queryType, string query, params object[] parameters)
        {
            return ExecuteScalar(queryType, query, PackageParameters(parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(rbQueryType queryType, string query, rbParameters parms)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parms;
            request.QueryText = query;
            request.QueryType = queryType;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteScalar(request, this.rb.Connection.ProviderSignature);

            return response.Scalar;
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(string schema, string storedProcedure)
        {
            return ExecuteScalar(schema, storedProcedure, null as rbParameters);
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(string schema, string storedProcedure, params object[] parameters)
        {
            return ExecuteScalar(schema, storedProcedure, PackageParameters(parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>第一行第一列的值.</returns>
        protected object ExecuteScalar(string schema, string storedProcedure, rbParameters parameters)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parameters;
            request.Schema = schema;
            request.QueryText = storedProcedure;
            request.QueryType = rbQueryType.StoredProcedure;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteScalar(request, this.rb.Connection.ProviderSignature);

            return response.Scalar;
        }

        #endregion

        #region ExecuteScalar<T>

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(rbQueryType queryType, string query)
        {
            return (T)ExecuteScalar<T>(queryType, query, null as rbParameters);
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(rbQueryType queryType, string query, params object[] parameters)
        {
            return (T)ExecuteScalar<T>(queryType, query, PackageParameters(parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(rbQueryType queryType, string query, rbParameters parms)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parms;
            request.QueryText = query;
            request.QueryType = queryType;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteScalar(request, this.rb.Connection.ProviderSignature);

            if (response.Scalar == DBNull.Value)
            {
                response.Scalar = null;
            }

            return (T)response.Scalar;
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(string schema, string storedProcedure)
        {
            return (T)ExecuteScalar<T>(schema, storedProcedure, null as rbParameters);
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(string schema, string storedProcedure, params object[] parameters)
        {
            return (T)ExecuteScalar<T>(schema, storedProcedure, PackageParameters(parameters));
        }

        /// <summary>
        /// 执行查询，并返回查询所返回的结果集中第一行的第一列.忽略其他列或行.并且将返回值转换为T类型
        /// 不能用该方法填充rbEntity.
        /// </summary>
        /// <remarks>
        /// 请参阅.NET文档的ExecuteScalar.
        /// </remarks>
        /// <example>
        /// 请参阅 <see cref="ExecuteNonQuery"/> 例子,重载和参数.
        /// </example>
        /// <returns>T.</returns>
        protected T ExecuteScalar<T>(string schema, string storedProcedure, rbParameters parameters)
        {
            rbDataRequest request = this.CreateRequest();

            request.Parameters = parameters;
            request.Schema = schema;
            request.QueryText = storedProcedure;
            request.QueryType = rbQueryType.StoredProcedure;

            rbDataProvider provider = new rbDataProvider();
            rbDataResponse response = provider.ExecuteScalar(request, this.rb.Connection.ProviderSignature);

            if (response.Scalar == DBNull.Value)
            {
                response.Scalar = null;
            }

            return (T)response.Scalar;
        }

        #endregion

        #region Graph Operations

        #region AcceptChangesGraph()

        /// <summary>
        /// graph对象可以调用.
        /// </summary>
        public void AcceptChangesGraph()
        {
            rbVisitor.Visit(this, AcceptChangesGraphCallback);
        }

        private bool AcceptChangesGraphCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Entity)
            {
                if (p.Node.Entity.GetCollection() == null)
                {
                    p.Node.Entity.AcceptChanges();
                }
            }
            else
            {
                p.Node.Collection.AcceptChanges();
            }

            return true;
        }

        #endregion

        #region RejectChangesGraph()

        /// <summary>
        /// 
        /// </summary>
        public void RejectChangesGraph()
        {
            rbVisitor.Visit(this, RejectChangesGraphCallback);
        }

        private bool RejectChangesGraphCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Entity)
            {
                if (p.Node.Entity.GetCollection() == null)
                {
                    p.Node.Entity.RejectChanges();
                }
            }
            else
            {
                p.Node.Collection.RejectChanges();
            }

            return true;
        }

        #endregion

        #region PruneGraph()

        /// <summary>
        /// 
        /// </summary>
        public void PruneGraph()
        {
            rbVisitor.Visit(this, PruneGraphEnterCallback, PruneGraphExitCallback);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="statesToPrune">修改的状态, 有很多如PruneGraph(rbDataRowState.Modified | rbDataRowState.Deleted)</param>
        public void PruneGraph(rbDataRowState statesToPrune)
        {
            rbVisitor.Visit(this, PruneGraphWithStateEnterCallback, PruneGraphWithStatExitCallback, statesToPrune);
        }

        private bool PruneGraphEnterCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Collection)
            {
                p.Node.UserState = new List<rbEntity>();
            }

            if (p.Node.NodeType == rbVisitableNodeType.Entity)
            {
                if (p.Node.Entity.GetCollection() == null)
                {
                    if (!p.Node.Entity.rb.IsDirty && !p.Node.Entity.rb.IsGraphDirty)
                    {
                        p.Node.SetValueToNull(p.Parent.Obj);
                    }
                }
                else if (!p.Node.Entity.rb.IsDirty && !p.Node.Entity.rb.IsGraphDirty)
                {
                    List<rbEntity> list = p.Parent.UserState as List<rbEntity>;
                    list.Add(p.Node.Entity);
                }
            }
            else
            {
                p.Node.UserState = new List<rbEntity>();

                if (!p.Node.Collection.IsDirty && !p.Node.Collection.IsGraphDirty)
                {
                    p.Node.SetValueToNull(p.Parent.Obj);
                }
            }

            return true;
        }

        private bool PruneGraphExitCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Collection)
            {
                rbEntityCollectionBase coll = p.Node.Collection as rbEntityCollectionBase;

                List<rbEntity> list = p.Node.UserState as List<rbEntity>;

                foreach (rbEntity entity in list)
                {
                    coll.RemoveEntity(entity);
                }

                if (coll.Count == 0 && !coll.Count.Equals(p.Root))
                {
                    p.Node.SetValueToNull(p.Parent.Obj);
                }
            }

            return true;
        }

        private bool PruneGraphWithStateEnterCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Collection)
            {
                p.Node.UserState = new List<rbEntity>();
            }

            if (p.Node.NodeType == rbVisitableNodeType.Entity)
            {
                if (p.Node.Entity.GetCollection() == null)
                {
                    if (MatchesState(p.Node.Entity.rb.RowState, (rbDataRowState)p.UserState))
                    {
                        p.Node.SetValueToNull(p.Parent.Obj);
                    }
                }
                else if (MatchesState(p.Node.Entity.rb.RowState, (rbDataRowState)p.UserState))
                {
                    List<rbEntity> list = p.Parent.UserState as List<rbEntity>;
                    list.Add(p.Node.Entity);
                }
            }
            else
            {
                p.Node.UserState = new List<rbEntity>();

                if (MatchesState(rbDataRowState.Deleted, (rbDataRowState)p.UserState))
                {
                    p.Node.Collection.ClearDeletedEntries();
                }

                bool canSetToNull = true;
                foreach (rbEntity entity in p.Node.Collection)
                {
                    if (!MatchesState(entity.rb.RowState, (rbDataRowState)p.UserState))
                    {
                        canSetToNull = false;
                        break;
                    }
                }

                if (canSetToNull)
                {
                    p.Node.SetValueToNull(p.Parent.Obj);
                }
            }

            return true;
        }

        private bool PruneGraphWithStatExitCallback(rbVisitParameters p)
        {
            if (p.Node.NodeType == rbVisitableNodeType.Collection)
            {
                rbEntityCollectionBase coll = p.Node.Collection as rbEntityCollectionBase;

                List<rbEntity> list = p.Node.UserState as List<rbEntity>;

                foreach (rbEntity entity in list)
                {
                    coll.RemoveEntity(entity);
                }

                if (coll.Count == 0 && !coll.Count.Equals(p.Root))
                {
                    p.Node.SetValueToNull(p.Parent.Obj);
                }
            }

            return true;
        }

        static private bool MatchesState(rbDataRowState theState, rbDataRowState statesToPrune)
        {
            return (theState == (statesToPrune & theState)) ? true : false;
        }

        #endregion

        #endregion

        #region IEditableObject Members

        /// <summary>
        /// 此方法可以备份所有的值，以便在编辑过程中调用<see cref="CancelEdit"/>方法的时候可以恢复值. 
        /// <see cref="EndEdit"/> 将建议值作为当前值.
        /// </summary>
        void IEditableObject.BeginEdit()
        {
            if (isInEditMode) return;

            isInEditMode = true;

            backupValues = currentValues;
            currentValues = proposedValues = new rbSmartDictionary(currentValues);

            originalRowState = rowState;
            originalModifiedColumns = m_modifiedColumns;
        }

        /// <summary>
        /// 当开始编辑的时候，恢复在处理<see cref="BeginEdit"/>的时候捕获的原始值. 
        /// <see cref="EndEdit"/> 将建议值作为当前值.
        /// </summary>
        void IEditableObject.CancelEdit()
        {
            if (!isInEditMode) return;

            isInEditMode = false;

            currentValues = backupValues;
            proposedValues = backupValues = null;
            rowState = originalRowState;
            m_modifiedColumns = originalModifiedColumns;
        }

        /// <summary>
        /// 当EndEdit调用的时候，建议值变为当前值得. 
        /// </summary>
        /// <seealso cref="BeginEdit"/><seealso cref="CancelEdit"/>
        void IEditableObject.EndEdit()
        {
            if (!isInEditMode) return;

            isInEditMode = false;

            currentValues = proposedValues;
            originalRowState = rbDataRowState.Invalid;
            proposedValues = backupValues = null;
            originalModifiedColumns = null;
        }

        #endregion

        #region IEntity属性

        /// <summary>
        /// 连接信息
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        rbConnection IEntity.Connection
        {
            get
            {
                if (this.connection == null)
                {
                    this.connection = new rbConnection();

                    if (rbConnection.ConnectionService != null)
                    {
                        this.connection.Name = rbConnection.ConnectionService.GetName();
                    }
                    else
                    {
                        // Make it so if they access this they get the 
                        // Collections Connection info
                        if (this.Collection != null)
                        {
                            IEntityCollection ec = this.Collection as IEntityCollection;
                            this.connection.Name = ec.Connection.Name;
                        }
                        else
                        {
                            string connName = this.GetConnectionName();
                            if (connName != null)
                            {
                                this.connection.Name = connName;
                            }
                        }
                    }
                }
                return this.connection;
            }
            set { this.connection = value; }
        }

        /// <summary>
        /// 修改的列的列表
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        List<string> IEntity.ModifiedColumns
        {
            get
            {
                if (this.m_modifiedColumns == null)
                {
                    this.m_modifiedColumns = new List<string>();
                }

                return m_modifiedColumns;
            }
        }

        /// <summary>
        /// 实体的目录
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.Catalog
        {
            get
            {
                if (this.rb.Connection.Catalog != null)
                    return this.rb.Connection.Catalog;
                else
                    return this.GetProviderMetadata().Catalog;
            }
        }

        /// <summary>
        /// 实体的架构
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.Schema
        {
            get
            {
                if (this.rb.Connection.Schema != null)
                    return this.rb.Connection.Schema;
                else
                    return this.GetProviderMetadata().Schema;
            }
        }

        /// <summary>
        /// 实体的目标名称.实体将被保存到表
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.Destination
        {
            get { return this.GetProviderMetadata().Destination; }
        }

        /// <summary>
        /// The source of this entity
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.Source
        {
            get { return this.GetProviderMetadata().Source; }
        }

        /// <summary>
        /// 存储过程'INSERT'的名称
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.spInsert
        {
            get { return this.GetProviderMetadata().spInsert; }
        }

        /// <summary>
        /// 存储过程'UPDATE'的名称
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.spUpdate
        {
            get { return this.GetProviderMetadata().spUpdate; }
        }

        /// <summary>
        /// 存储过程'DELETE'的名称
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.spDelete
        {
            get { return this.GetProviderMetadata().spDelete; }
        }

        /// <summary>
        /// 存储过程'LoadAll'的名称
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.spLoadAll
        {
            get { return this.GetProviderMetadata().spLoadAll; }
        }

        /// <summary>
        /// 存储过程'LoadByPrimaryKey'的名称
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.spLoadByPrimaryKey
        {
            get { return this.GetProviderMetadata().spLoadByPrimaryKey; }
        }

        /// <summary>
        /// rbEntity已加载数据并且没有标记为Deleted，返回true.一个rbEntity代表一行数据，然而完整的语法允许加载一个rbEntity. 请参阅 <see cref="rbDynamicQuery"/>
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.HasData
        {
            get
            {
                if ((currentValues.Count > 0 && rb.RowState != rbDataRowState.Deleted) || collection != null)
                    return true;
                else
                    return false;
            }
        }

        /// <summary>
        /// 如果调用AddNew(), MarkAsDeleted(),或任何实体表的基础属性发生改变,设置为true.
        /// 成功调用<see cref="Save"/> 之后，返回 false.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.IsDirty
        {
            get
            {
                switch (rowState)
                {
                    case rbDataRowState.Added:
                        return true;

                    case rbDataRowState.Modified:
                        return true;

                    case rbDataRowState.Deleted:
                        return true;
                }

                return false;
            }
        }

        /// <summary>
        /// Graph对象中的任何实体或实体集合的IsDirty属性返回true,那么返回true.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.IsGraphDirty
        {
            get
            {
                if (this.rb.IsDirty) return true; 

                return !rbVisitor.Visit(this, IsGraphDirtyCallback);
            }
        }

        private bool IsGraphDirtyCallback(rbVisitParameters p)
        {
            bool isClean = true;

            if (p.Node.NodeType == rbVisitableNodeType.Entity)
            {
                if (p.Node.Entity.GetCollection() == null)
                {
                    isClean = !p.Node.Entity.rb.IsDirty;
                }
            }
            else
            {
                isClean = !p.Node.Collection.IsDirty;
            }

            if (!isClean)
            {
                p.ProcessChildren = false;
            }

            return isClean;
        }

        /// <summary>
        /// 如果RowState是rbDataRowState.Modified返回true.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.IsModified
        {
            get
            {
                return rowState == rbDataRowState.Modified;
             }
        }

        /// <summary>
        /// 如果RowState是rbDataRowState.Added返回true.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.IsAdded
        {
            get
            {
                return rowState == rbDataRowState.Added;
            }
        }

        /// <summary>
        /// 如果RowState是rbDataRowState.Deleted返回true.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        bool IEntity.IsDeleted
        {
            get
            {
                return rowState == rbDataRowState.Deleted;
            }
        }

        /// <summary>
        /// 请参阅ADO.NET rbDataRowState 枚举获取更多信息. 
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        rbDataRowState IEntity.RowState
        {
            get
            {
                return rowState;
            }

            set
            {
                switch (value)
                {
                    case rbDataRowState.Added:
                        rowState = value;
                        break;

                    case rbDataRowState.Deleted:
                        throw new Exception("Call instead rbEntity.MarkAsDeleted()");

                    case rbDataRowState.Modified:
                        rowState = value;
                        break;

                    case rbDataRowState.Unchanged:
                        throw new Exception("Call instead AcceptChanges()");
                }
            }
        }

        /// <summary>
        /// 请参阅ADO.NET DataRow.RowError获取更多信息.
        /// </summary>
#if (!WindowsCE)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
#endif
        string IEntity.RowError
        {
            get
            {
                return rowError;
            }
        }

        /// <summary>
        /// 允许你访问元数据
        /// </summary>
        IMetadata IEntity.Meta
        {
            get { return this.Meta; }
        }

        /// <summary>
        /// 如果为true,禁用延迟加载
        /// </summary>
        bool IEntity.IsLazyLoadDisabled
        {
            get { return this._isLazyLoadDisabled; }
            set { this._isLazyLoadDisabled = value; }
        }

        /// <summary>
        /// 动态查询的预读取逻辑内部调用
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        rbEntityCollectionBase IEntity.CreateCollection(string name)
        {
            return this.CreateCollectionForPrefetch(name);
        }

        #endregion

        #region ICommittable属性

        bool ICommittable.Commit()
        {
            AcceptChanges();
            return true;
        }

        #endregion

        #region ICustomTypeDescriptor Members

        // 在web中为了扩展列可以绑定需要这些

        #if (WebBinding)

        System.ComponentModel.AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return new System.ComponentModel.AttributeCollection(null);
        }

        string ICustomTypeDescriptor.GetClassName()
        {
            return null;
        }

        string ICustomTypeDescriptor.GetComponentName()
        {
            return null;
        }

        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return null;
        }

        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return null;
        }

        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return null;
        }

        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return null;
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return new EventDescriptorCollection(null);
        }

        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return new EventDescriptorCollection(null);
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            if (this.Collection == null)
            {
                return null;
            }

            ITypedList tl = this.Collection as ITypedList;
            return tl.GetItemProperties(null);
        }

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            if (this.Collection == null)
            {
                return null;
            }

            ITypedList tl = this.Collection as ITypedList;
            return tl.GetItemProperties(null);
        }

        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }
#endif

        #endregion

        #region Hierarchical Support

        /// <summary>
        /// 当保存实体中正在改变的层次化的属性需要rbTransactionScope的时候，为true.
        /// 如果为true，自动创建rbTransactionScope事务.
        /// </summary>
        /// <returns></returns>
        private bool NeedsTransactionDuringSave()
        {
            bool needsTx = this.preSaves != null && this.preSaves.Count > 0;

            needsTx |= this.postSaves != null && this.postSaves.Count > 0;
            needsTx |= this.postOneSaves != null && this.postOneSaves.Count > 0;

            return needsTx;
        }

        #region PreSaves
        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected rbEntity GetPreSave(string name)
        {
            if (preSaves != null)
            {
                if (preSaves.ContainsKey(name))
                {
                    return preSaves[name];
                }
            }

            return null;
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        protected void RemovePreSave(string name)
        {
            if (preSaves != null)
            {
                if (preSaves.ContainsKey(name))
                {
                    preSaves.Remove(name);
                }
            }
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="entity"></param>
        protected void SetPreSave(string name, rbEntity entity)
        {
            if (preSaves == null)
            {
                preSaves = new Dictionary<string, rbEntity>();
            }

            preSaves[name] = entity;
        }

        /// <summary>
        /// 内部调用
        /// </summary>
        internal protected void CommitPreSaves()
        {
            if (this.preSaves != null)
            {
                foreach (rbEntity entity in this.preSaves.Values)
                {
                    entity.Save();
                }
            }
        }
        #endregion

        #region PostSaves
        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected rbEntityCollectionBase GetPostSave(string name)
        {
            if (postSaves != null)
            {
                if (postSaves.ContainsKey(name))
                {
                    return postSaves[name];
                }
            }

            return null;
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        protected void RemovePostSave(string name)
        {
            if (postSaves != null)
            {
                if (postSaves.ContainsKey(name))
                {
                    postSaves.Remove(name);
                }
            }
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="coll"></param>
        protected void SetPostSave(string name, rbEntityCollectionBase coll)
        {
            if (postSaves == null)
            {
                postSaves = new Dictionary<string, rbEntityCollectionBase>();
            }

            postSaves[name] = coll;
        }

        /// <summary>
        /// 内部调用.
        /// </summary>
        internal protected void CommitPostSaves()
        {
            if (postSaves != null)
            {
                foreach (rbEntityCollectionBase coll in this.postSaves.Values)
                {
                    coll.Save();
                }
            }
        }
        #endregion

        #region PostOneSaves
        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        protected rbEntity GetPostOneSave(string name)
        {
            if (postOneSaves != null)
            {
                if (postOneSaves.ContainsKey(name))
                {
                    return postOneSaves[name];
                }
            }

            return null;
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        protected void RemovePostOneSave(string name)
        {
            if (postOneSaves != null)
            {
                if (postOneSaves.ContainsKey(name))
                {
                    postOneSaves.Remove(name);
                }
            }
        }

        /// <summary>
        /// 层次化逻辑的一部分内部调用.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="entity"></param>
        protected void SetPostOneSave(string name, rbEntity entity)
        {
            if (postOneSaves == null)
            {
                postOneSaves = new Dictionary<string, rbEntity>();
            }

            postOneSaves[name] = entity;
        }

        /// <summary>
        /// 内部调用.
        /// </summary>
        internal protected void CommitPostOneSaves()
        {
            if (postOneSaves != null)
            {
                foreach (rbEntity entity in this.postOneSaves.Values)
                {
                    entity.Save();
                }
            }
        }
        #endregion

        [NonSerialized]
        private Dictionary<string, rbEntity> preSaves;
        [NonSerialized]
        private Dictionary<string, rbEntityCollectionBase> postSaves;
        [NonSerialized]
        private Dictionary<string, rbEntity> postOneSaves;
        #endregion

        #region IDataErrorInfo Members

        string IDataErrorInfo.Error
        {
            get
            {
                return ((IDataErrorInfo)this)[string.Empty];
            }
        }

        string IDataErrorInfo.this[string columnName]
        {
            get
            {
                string result = string.Empty;

                // First let's assume this is the property name
                rbColumnMetadata columnMeta = this.Meta.Columns.FindByPropertyName(columnName);

                if (columnMeta == null)
                {
                    // nope, it must be the column name
                    columnMeta = this.Meta.Columns.FindByColumnName(columnName);
                }

                if (this.onValidateDelegate != null)
                {
                    result = onValidateDelegate(columnName, this, columnMeta);
                }

                if (string.IsNullOrEmpty(result))
                {
                    result = this.Validate(columnName, this, columnMeta);
                }

                return result;
            }
        }

        /// <summary>
        /// 在生成的类中重写，提供验证
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="entity"></param>
        /// <param name="metadata"></param> 
        /// <returns></returns>
        virtual public string Validate(string columnName, rbEntity entity, rbColumnMetadata metadata)
        {
            return string.Empty;
        }

        /// <summary>
        /// 委托验证
        /// </summary>
        /// <param name="columnName"></param>
        /// <param name="entity"></param>
        /// <param name="metadata"></param> 
        /// <returns></returns>
        public delegate string ValidateDelegate(string columnName, rbEntity entity, rbColumnMetadata metadata);

        /// <summary>
        /// 用于提供验证.
        /// </summary> 
        public event ValidateDelegate OnValidateDelegate
        {
            add
            {
                onValidateDelegate += value;
            }
            remove
            {
                onValidateDelegate -= value;
            }
        }

        [NonSerialized]
#if (!WindowsCE)
        [IgnoreDataMember]
#endif
        private ValidateDelegate onValidateDelegate;

        #endregion

        #region IVisitable

        rbVisitableNode[] IVisitable.GetGraph(object state)
        {
            Type type = this.GetType();

            FieldInfo[] fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
            FieldInfo field = null;

            List<rbVisitableNode> references = new List<rbVisitableNode>();

            for (int i = 0; i < fields.Length; i++)
            {
                field = fields[i];

                object o = field.GetValue(this);

                if (o != null)
                {
                    if (typeof(rbEntity).IsAssignableFrom(field.FieldType))
                    {
                        references.Add(new rbVisitableNode() { Obj = o, PropertyName = field.Name, fieldInfo = field });
                    }
                    else if (typeof(rbEntityCollectionBase).IsAssignableFrom(field.FieldType))
                    {
                        references.Add(new rbVisitableNode() { Obj = o, PropertyName = field.Name, fieldInfo = field });
                    }
                }
            }

            return references.ToArray();
        }

        #endregion

        #region Fields

        [NonSerialized]
        private rbEntityCollectionBase collection;

        [NonSerialized]
        private bool isInEditMode;

        [NonSerialized]
        private rbConnection connection;

        [NonSerialized]
        private rbDataRowState originalRowState;

        [NonSerialized]
        private List<string> originalModifiedColumns;

        [NonSerialized]
        private rbSmartDictionary proposedValues;

        [NonSerialized]
        private rbSmartDictionary backupValues;

        [NonSerialized]
        private Dictionary<string, int> selectedColumns;

        [NonSerialized]
        internal string rowError;

        [NonSerialized]
        internal bool _isLazyLoadDisabled;

        [NonSerialized]
        private bool applyDefaultsCalled;

        /// <summary>
        /// 已修改的列的名称集合
        /// </summary>
        internal List<string> m_modifiedColumns;

        internal rbSmartDictionary originalValues;

        internal rbSmartDictionary currentValues = new rbSmartDictionary();

        internal rbDataRowState rowState = rbDataRowState.Unchanged;

        #endregion

#if (!WindowsCE)
        #region DataContract Serialization Trickery

        [OnDeserialized]
        internal void OnDeserialized(StreamingContext context)
        {
            this.m_modifiedColumns = tempModifiedColumns;
            tempModifiedColumns = null;

            this.rowState = tempRowState;

            if (originalValues == null)
            {
                originalValues = new rbSmartDictionary(currentValues);
            }
        }

        [XmlIgnore]
        [DataMember(Name = "RowState", EmitDefaultValue = false)]
        private rbDataRowState TempRowState
        {
            get { return rb.RowState; }
            set { tempRowState = value; }
        }

        [NonSerialized]
        [IgnoreDataMember]
        private rbDataRowState tempRowState;

        [XmlIgnore]
        [DataMember(Name = "ModifiedColumns", EmitDefaultValue=false)]
        private List<string> TempModifiedColumns
        {
            get { return m_modifiedColumns; }
            set { tempModifiedColumns = value; }
        }

        [NonSerialized]
        [IgnoreDataMember]
        private List<string> tempModifiedColumns;

        #endregion
#endif

        #region ModifiedBy Hooks
        /// <summary>
        /// 
        /// </summary>
        static public event ModifiedByEventHandler AddedByEventHandler;
        /// <summary>
        /// 
        /// </summary>
        static public event ModifiedByEventHandler ModifiedByEventHandler;

        #endregion
    }
}
